#include <iostream>
using namespace std;
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include "PartStore.h"


/*============================================<配件类实现>============================================*/
Part::Part(int id, string name, string model, double price, string location, int stockQuantity, int stockUpperLimit, int stockLowerLimit) :
    id(id), name(name), model(model), price(price), location(location), stockQuantity(stockQuantity), stockUpperLimit(stockUpperLimit), stockLowerLimit(stockLowerLimit) {}
Part::~Part() {}

int Part::getId()const { return this->id; }
string Part::getName()const { return this->name; }
string Part::getModel()const { return this->model; }
double Part::getPrice()const { return this->price; }
string Part::getLocation()const { return this->location; }
int Part::getStockQuantity()const { return this->stockQuantity; }
int Part::getStockUpperLimit()const { return this->stockUpperLimit; }
int Part::getStockLowerLimit()const { return this->stockLowerLimit; }

void Part::setLocation(std::string location) {this->location = location;}
void Part::setStockQuantity(int quantity) { this->stockQuantity = quantity; }

string Part::serialize(void)
{
    return to_string(id) + "|" + name + "|" + model + "|" + to_string(price) + "|" + location
        + "|" + to_string(stockQuantity) + "|" + to_string(stockUpperLimit) + "|" + to_string(stockLowerLimit)+"\n";
}

int Part::deSerialize(const std::string& str)
{
    istringstream iss(str);
    string token;
    getline(iss, token, '|');
    id = stoi(token);
    getline(iss, token, '|');
    name = token;
    getline(iss, token, '|');
    model = token;
    getline(iss, token, '|');
    price = stod(token);
    getline(iss, token, '|');
    location = token;
    getline(iss, token, '|');
    stockQuantity = stoi(token);
    getline(iss, token, '|');
    stockUpperLimit = stoi(token);
    getline(iss, token, '\n');
    stockLowerLimit = stoi(token);

    return 0;
}

/*============================================<仓库记录类实现>============================================*/
StoreRecord::StoreRecord(const int& recordId, const int& partId,const myTime_t& operationTime,const string& status) :
    recordId(recordId), partId(partId), operationTime(operationTime), status(status) {}
StoreRecord::~StoreRecord() {}

int StoreRecord::getrecordId()const { return recordId; }
int StoreRecord::getPartId()const { return this->partId; }
myTime_t StoreRecord::getOperationTime()const { return this->operationTime; }
string StoreRecord::getStatus()const { return this->status; }

string StoreRecord::serialize(void)
{
    return to_string(recordId) + "|" + to_string(partId) + "|" + operationTime + "|" + status;
}

int StoreRecord::deSerialize(const std::string& str)
{
    istringstream iss(str);
    string token;
    getline(iss, token, '|');
    recordId = stoi(token);
    getline(iss, token, '|');
    partId = stoi(token);
    getline(iss, token, '|');
    operationTime = token;
    getline(iss, token, '|');
    status = token;

    return 0;
}

/*============================================<仓库入库记录类实现>============================================*/
StoreInRecord::StoreInRecord(const int& recordId, const int& partId, const myTime_t& operationTime, const string& status, const int& inQuantity) :
    StoreRecord(recordId, partId, operationTime, status), inQuantity(inQuantity) {}
StoreInRecord::StoreInRecord(const StoreRecord& sr, const int& inQuantity) : StoreRecord(sr), inQuantity(inQuantity) {}
StoreInRecord::~StoreInRecord() {}

int StoreInRecord::getInQuantity()const { return this->inQuantity; }

string StoreInRecord::serialize(void)
{
    return StoreRecord::serialize() + "|" + to_string(inQuantity) + "\n";
}


int StoreInRecord::deSerialize(const std::string& str)//豆包优化，使用了try catch具有较高的代码健壮性，作为参考
{
    if (StoreRecord::deSerialize(str) != 0)
        return -1;
    

    size_t lastPipePos = str.rfind('|');//rfind函数返回找到的最后一个'|'的位置，如果找不到，则返回npos
    if (lastPipePos != std::string::npos)//如果找到了最后一个'|'的位置，则执行以下代码
    {
        std::string quantityStr = str.substr(lastPipePos + 1);//substr函数返回从lastPipePos+1开始的子字符串
        // 去掉换行符
        size_t newlinePos = quantityStr.find('\n');
        if (newlinePos != std::string::npos)
        {
            quantityStr = quantityStr.substr(0, newlinePos);
        }
        try
        {
            inQuantity = std::stoi(quantityStr);
        }
        catch (const std::invalid_argument& e)
        {
            std::cerr << "Invalid argument in StoreInRecord::deSerialize: " << e.what() << std::endl;
            return -1;
        }
        catch (const std::out_of_range& e)
        {
            std::cerr << "Out of range in StoreInRecord::deSerialize: " << e.what() << std::endl;
            return -1;
        }
    }

    return 0;
}


/*============================================<仓库出库记录类实现>============================================*/
StoreOutRecord::StoreOutRecord(const StoreRecord& sr, const int& outQuantity) :StoreRecord(sr), outQuantity(outQuantity) {}
StoreOutRecord::StoreOutRecord(const int& recordId, const int& partId, const myTime_t& operationTime, const string& status, const int& outQuantity) :
    StoreRecord(recordId, partId, operationTime, status), outQuantity(outQuantity) {}

StoreOutRecord::~StoreOutRecord() {}

int StoreOutRecord::getOutQuantity()const { return this->outQuantity; }

string StoreOutRecord::serialize(void)
{
    return StoreRecord::serialize() + "|" + to_string(outQuantity) + "\n";
}

int StoreOutRecord::deSerialize(const std::string& str)
{
    if (StoreRecord::deSerialize(str) != 0)
        return -1;

    size_t lastPipepos = str.rfind("|");
    if (lastPipepos != std::string::npos)
    {
        std::string quantityStr = str.substr(lastPipepos + 1);
        size_t newlinePos = quantityStr.find('\n');
        if (newlinePos != std::string::npos)
        {
            quantityStr = quantityStr.substr(0, newlinePos);
        }
        this->outQuantity = std::stoi(quantityStr);
    }

    return 0;
}

/*============================================<仓库异常库记录类实现>============================================*/

StoreAnomaly::StoreAnomaly(const int& anomalyId, const int& partId, const int& actualQuantity, const int& systemQuantity, const string& difference, const string& confirmStatus) :
    anomalyId(anomalyId), partId(partId), actualQuantity(actualQuantity), systemQuantity(systemQuantity), difference(difference), confirmStatus(confirmStatus) {
}

StoreAnomaly::StoreAnomaly(const int& anomalyId, const int& partId, const string& location, const int& actualQuantity, const int& systemQuantity, const string& difference, const std::string& confirmStatus) :
    anomalyId(anomalyId), partId(partId), location(location), actualQuantity(actualQuantity), systemQuantity(systemQuantity), difference(difference), confirmStatus(confirmStatus) {
}

StoreAnomaly::~StoreAnomaly() {}


int StoreAnomaly::getAnomalyId()const { return this->anomalyId; }
int StoreAnomaly::getPartId()const { return this->partId; }
std::string StoreAnomaly::getLocation()const { return this->location; }
int StoreAnomaly::getActualQuantity()const { return this->actualQuantity; }
int StoreAnomaly::getSystemQuantity()const { return this->systemQuantity; }
string StoreAnomaly::getDifference()const { return this->difference; }
string StoreAnomaly::getConfirmStatus()const { return this->confirmStatus; }

void StoreAnomaly::setAnomalyId(int anomalyId) {this->anomalyId = anomalyId;}
void StoreAnomaly::setDifference(std::string difference){this->difference = difference;}
void StoreAnomaly::setConfirmStatus(std::string confirmStatus) { this->confirmStatus = confirmStatus; }

string StoreAnomaly::serialize(void)
{
    return to_string(anomalyId) + "|" + to_string(partId) + "|" + location + "|" + to_string(actualQuantity)
        + "|" + to_string(systemQuantity) + "|" + (difference) + "|" + confirmStatus + "\n";
}

int StoreAnomaly::deSerialize(const std::string& str)
{
    istringstream iss(str);
    string token;
    getline(iss, token, '|');
    anomalyId = stoi(token);
    getline(iss, token, '|');
    partId = stoi(token);
    getline(iss, token, '|');
    location = (token);
    getline(iss, token, '|');
    actualQuantity = stoi(token);
    getline(iss, token, '|');
    systemQuantity = stoi(token);
    getline(iss, token, '|');
    difference = (token);
    getline(iss, token, '\n');
    confirmStatus = token;
    return 0;
}

/*============================================<日志类实现>============================================*/

LogEntry::LogEntry(const int& logId, const myTime_t& operationTime, const std::string& operatorName, const Role& operatorRole, const std::string& operationDescribe) :
    logId(logId), operationTime(operationTime), operatorName(operatorName),operatorRole(operatorRole) ,operationDescribe(operationDescribe) {}
LogEntry::~LogEntry() {}

int LogEntry::getLogId()const { return this->logId; }
myTime_t LogEntry::getOperationTime()const { return this->operationTime; }
string LogEntry::getOperatorName()const { return this->operatorName; }
Role LogEntry::getOperatorRole()const { return this->operatorRole; }
string LogEntry::getOperationDescribe()const { return this->operationDescribe; }

string LogEntry::serialize(void)
{
    string tmpStr;
    switch (this->operatorRole)
    {
        case Role::ADMIN:tmpStr = "管理员";break;
        case Role::USER_INFO:tmpStr = "配件信息录入人员";break;
        case Role::USER_STORE_IO:tmpStr = "仓库管理人员";break;
        case Role::USER_STORE_CHECK:tmpStr = "仓库盘点人员";break;
    }
    return to_string(logId) + "|" + operationTime + "|" + (operatorName)+ "|" + tmpStr + "|" + operationDescribe + "\n" ;
}

int LogEntry::deSerialize(const std::string& str)
{
    istringstream iss(str);
    string token;
    getline(iss, token, '|');
    logId = stoi(token);
    getline(iss, token, '|');
    operationTime = token;
    getline(iss, token, '|');
    operatorName = (token);

    getline(iss, token, '|');
    if (token == "管理员")
        operatorRole = Role::ADMIN;
    else if (token == "配件信息录入人员")
        operatorRole = Role::USER_INFO;
    else if (token == "仓库管理人员")
        operatorRole = Role::USER_STORE_IO;
    else if (token == "仓库盘点人员")
        operatorRole = Role::USER_STORE_CHECK;
    
    getline(iss, token, '\n');
    operationDescribe = token;
    return 0;
}